package com.aldobucchi.ds.op
{
	
	

	import com.aldobucchi.ds.DataStructureEvent;
	import com.aldobucchi.ds.container.ContainerDiff;
	import com.aldobucchi.ds.container.IRContainer;
	import com.aldobucchi.ds.container.zet.IOSet;
	import com.aldobucchi.ds.container.zet.IWSet;





	public class SetMultiFilterOp extends AbstractContainerToSetOp
	{
		
		private var iFilterFunctions:IOSet;
		
		public function SetMultiFilterOp( iContainer:IRContainer, oSet:IWSet, iFilterFunctions:IOSet )
		{
			
			this.iFilterFunctions = iFilterFunctions;
			
			super( iContainer, oSet );
			
			refresh( );
			
			iFilterFunctions.addEventListener( DataStructureEvent.CHANGE, iFilterFunctions_change );
			
		}
		


		
		
		private function refresh( ):void
		{
		
		
			oSet.autoUpdateFlag.disable( );

			oSet.clear( );
			
			iContainer.walk( function( e:*, m:int ):void{
			
				if ( test( e ) )
				{
					oSet.add( e );
				}	
			
			} );			
			
			oSet.autoUpdateFlag.enable( );			
		
		}		
		
		
		
		
		
		private function test( e:* ):Boolean
		{
			
			for each ( var func:Function in iFilterFunctions.asArray )
				if ( func.apply( null, [ e ] ) == false )
					return false;			
			
			return true;			

		}
			
			
			
		
		override protected function iContainer_change(event:DataStructureEvent):void
		{
			
			
			oSet.autoUpdateFlag.disable( );				
			
		
				var diff:ContainerDiff = event.diff as ContainerDiff;
				
				diff.walk(
					
					function( e:*, multiplicity:int ):void
					{
						if ( test( e ) )
						{
							m( e, multiplicity );		
						}
					}			
				
				 );
		
					
			oSet.autoUpdateFlag.enable( );
			
		}
			
		
		
		private function m( e:*, m:int ):void
		{
			if ( m > 0 )
				oSet.add( e );
			else
				oSet.remove( e );
		}		
		
		
		
		private function iFilterFunctions_change( event:DataStructureEvent ):void
		{
		
			refresh( ); // TODO: optimize. we can store the result of each filter
						// and save us a lot of work
		
		}
		
		override public function dispose( ):void
		{
			super.dispose( );
			iFilterFunctions = null;		
			iFilterFunctions.removeEventListener( DataStructureEvent.CHANGE, iFilterFunctions_change );
		}
		
	}
	
}